﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using IFWiki.Utils;
using System.Xml.Serialization;

namespace IFWiki.Models
{
    public partial class GamePlace : IRevisable
    {
        /// <summary>
        /// The name of the place, for example 'The Town Square'
        /// This can contain spaces etc, don't limit yourself.
        /// </summary>
        public string PlaceName { get; set; }
        
        /// <summary>
        /// The game to which this place belongs.
        /// </summary>
        public string GameName { get; set; }

        [XmlIgnore()]
        public string Name
        {
            get
            {
                return PlaceName + "__game_" + GameName;
            }
        }

        /// <summary>
        /// A piece of javascript that is executed 
        /// every time the player enters this place.
        /// (This is run after the game runs its own 'OnPlaceEnter'
        /// javascript, which is one piece of code it runs for 
        /// every place in the game.)
        /// </summary>
        public string InitPlaceJS { get; set; }

        /// <summary>
        /// The text that *is* this page.
        /// Can include hidden sections (that are only revealed in certain circumstances)
        /// </summary>
        public string DescriptionMarkdown { get; set; }

        /// <summary>
        /// JSON to describe items that are in this place.
        /// They are added or removed from the place if the 
        /// player collects them.
        /// </summary>
        public string PlaceItemsJson { get; set; }

        /// <summary>
        /// Any style sheet information that is used in this place only
        /// e.g. If it's a "dark" room... you might make it dark!
        /// </summary>
        public string PlaceStyle { get; set; }

        public string Reason { get; set; }
        public DateTime RevisedAt { get; set; }
        public string RevisedBy { get; set; }
        public bool IsDiscussion { get { return false; } }

        public string InnerType { get { return "GamePlace"; } }
    }


    public partial class GamePlace
    {
        public GamePlace()
        {
            //parameterless, for serialization
        }

        public GamePlace(string name) 
        {
            name = name.Replace("__game_", "|");
            var nameParts = name.Split('|');
            string placeName = nameParts[0];
            string gameName = nameParts[1];

            Init(placeName, gameName);
        }

        public GamePlace(string placeName, string gameName)
        {
            Init(placeName, gameName);
        }

        private void Init(string placeName, string gameName)
        {
            //Every place must belong to a game. Even new places.
            Debug.Assert(!string.IsNullOrEmpty(gameName));

            this.PlaceName = placeName;
            this.GameName = gameName;

            if (!string.IsNullOrEmpty(placeName)&& !string.IsNullOrEmpty(gameName))
            {

                var savedGamePlace = (GamePlace)Persister.Load(this.Name, this.GetType()) ?? Defaults.GetGamePlace(placeName, gameName);
                this.PlaceName = savedGamePlace.PlaceName;
                this.GameName = savedGamePlace.GameName;
                this.DescriptionMarkdown = savedGamePlace.DescriptionMarkdown;
                this.InitPlaceJS = savedGamePlace.InitPlaceJS;
                this.PlaceItemsJson = savedGamePlace.PlaceItemsJson;
                this.PlaceStyle = savedGamePlace.PlaceStyle;
            }
        }

        public void Save(string reason, string revisedBy)
        {
            this.Reason = reason;
            this.RevisedAt = DateTime.Now;
            this.RevisedBy = revisedBy;
            Debug.Assert(!string.IsNullOrEmpty(this.Name));
            Persister.Save(this.Name, this, this.RevisedAt);            
        }

        internal static GamePlace Revert(string name, DateTime revisedAt, string revertedBy)
        {
            var gamePlace = LoadRevision(name, revisedAt);
            gamePlace.Save("revert from " + revisedAt.ToString(), revertedBy);
            return gamePlace;
        }

        public static GamePlace LoadRevision(string name, DateTime revisedAt)
        {
            return Persister.LoadRevision<GamePlace>(name, revisedAt, typeof(GamePlace));
        }

        public List<IRevisable> LoadRevisions()
        {
            var revisions = new List<IRevisable>();
            revisions = Persister.LoadList<IRevisable>(this.Name, typeof(GamePlace)); 
            return revisions;
        }

        private Game game = null;

        /// <summary>
        /// Any style sheet information that is used on every page of the game
        /// (including the intro screen of the game)
        /// </summary>
        [XmlIgnore()]
        public string GameStyle
        {
            get
            {
                if (game == null)
                {
                    game = new Game(this.GameName);
                }
                return game.GameStyle;
            }
        }

        
        /// <summary>
        /// Every time you enter a new place, this piece of Javascript is run
        /// (before the place runs its own starting script)
        /// For example, in a typical game you might make the player 1 hour 
        /// older every time they move from one place to the next
        /// </summary>
        [XmlIgnore()]
        public string OnPlaceEnterJS
        {
            get
            {
                if (game == null)
                {
                    game = new Game(this.GameName);
                }
                return game.OnPlaceEnterJS;
            }
        }


    }

}
